/**
 * Created by Administrator on 2017/1/15.
 */

var config = require('./config');

var MJ = require('../MJ/MJ');
var MJRoom = require('../MJ/room').MJRoom;

var Const = require('./const');
var SubCode = require('../subCode');

exports.GXDDZRoom = MJRoom.extend({
    _Rounds: 0,             // 总局数
    _curRounds: 0,          // 当前局数
    _baoIndex: 0,           // 摸宝后指定的位置
    _baoCard: 0,            // 宝牌


    init: function (rid, creator, msg) {
        this._super(rid, creator, msg);

        this._Rounds = msg.round;
        this._curRounds = 0;
        this._baoIndex = 0;
        this.setSaveReplay(true);
    },

    checkInit: function () {
        return this._super();
    },

    /******************************************************************
     * 重载的接口
     ******************************************************************/

    getRoomConfig: function () {
        var cfg = this._super();
        cfg.MJsettlementWait = 0;
        cfg.respDestroyIgnore = 1;
        return cfg;
    },

    //获取房间信息
    getInfo: function () {
        var info = this._super();

        info.rounds = this._Rounds;
        info.curRounds = this._curRounds;

        return info;
    },
    //获取本轮房间信息
    getRoundInfo: function () {
        var info = this._super();
        info._curRounds = this._curRounds;
        return info;
    },
    //重新连接信息
    getReconnectInfo: function (rePlayer) {
        var info = this._super(rePlayer);
        // this._baoIndex = 0;
        // var tingInfo = {};
        // var tingCards = [];
        // // if (rePlayer == this.getCurPlayer()) {
        // //     tingInfo = this.getTingInfo(rePlayer);
        // // }
        // // info["BaoTingData"] = tingInfo;
        // if (rePlayer.isBaoTing()) {
        //     tingCards = rePlayer._tingCards;
        // } else {
        //     tingInfo = this.getTingInfo(rePlayer);
        // }
        // info["BaoTingData"] = tingInfo;
        // info["TingCards"] = tingCards;
        return info;
    },
    //开始新一轮之前的事件
    onBeforeStartNewRound: function () {
        this._super();
        this._curRounds++;
        this._baoIndex = 0;
        this._baoCard = 0;
        if (this.isAgency() && this.getCurRound() == 1) {
            this.sendToAgency("onStartOfAgency", {"roomIndex": this.getOption("index")});
        }
    },
    //开始新一轮之后的事件
    onAfterStartNewRound: function () {
        this._super();
        this.preStartPlay();
    },
    //准备开始游戏
    preStartPlay: function () {
        this.initPlayersHandCards();  //初始化玩家手牌
        this.startPlay();
    },

    //开始游戏
    startPlay: function () {
        var dealer = this.getDealerIndex();

        this.enumPlayers(function (eIndex, ePlayer) {//循环检测是否有听牌的玩家
            if (eIndex != dealer) {
                var tings = ePlayer.checkTing();
                if (tings.length > 0) {
                    //this._hangupTask.addTingTask(eIndex, tings);
                }
                ePlayer.setTingCards(tings);//设置这个玩家要听的牌
            }
        }.bind(this));
        logger.debug("room=%d sendHangupTask in=JLMJ.startPlay", this.rid());
        this._sendHangupTask(this._startPlay);//发送挂起任务
    },
    //开始游戏
    _startPlay: function () {
        this._changeCurPlay(this.getDealerIndex());//设置庄家的位置发牌
        this._doCheckNewCardHangupTask();
    },

    onBeforePlayCard: function (player, msg, card) {
        var code = this._super(player, msg, card);
        if (code) {
            return code;
        }
    },

    //检查摸牌后玩家的挂起任务
    checkNewCardHangupTask: function () {
        var player = this.getCurPlayer();

        // var tings = player.checkTing();
        // if (!player.isBaoTing()) {
        //     player.setTingCards(tings);
        // }
        var huPattern = player.checkHu();//获取胡牌的牌型
        if (huPattern && huPattern != Const.Pattern.NONE) {//是能胡的牌型
            var rules = [];//记录加分玩法
            if (player.isFirstHand()) {//是摸的第一张牌
                if (player.getIndex() == this.getDealerIndex()) {
                    rules.push(Const.ScoreRule.TH);
                }
            } else if (player.isBaoTing()) {
                rules.push(Const.ScoreRule.BT);
            }
            if (this.getCurGang()) {
                rules.push(Const.ScoreRule.GSH);
            }

            //自摸
            var card = player.getLastCard() || player.getInitLastCard();
            this._hangupTask.addHuTask(player.getIndex(), card, player.getIndex(), huPattern, rules);
            if (player.isBaoTing()) {
                this._hangupTask.submitTask(player.getIndex(), MJ.Task.HU);
            }
        }
        var gangArray = player.checkGang();
        if (gangArray.length > 0) {
            if (!player.isBaoTing()) {
                this._hangupTask.addGangTask(player.getIndex(), gangArray);
            } else {
                var baGangArray = new Array();
                gangArray.forEach(function (gangInfo) {
                    if (gangInfo.gang == MJ.Gang.BA && !gangInfo.overdue) {
                        baGangArray.push(gangInfo);
                    }
                }.bind(this));
                if (baGangArray.length > 0) {
                    this._hangupTask.addGangTask(player.getIndex(), baGangArray);
                    this._hangupTask.submitTask(player.getIndex(), MJ.Gang.BA);
                }
            }
        }
    },
    //检查出牌后其它玩家的挂起任务
    checkPlayCardHangupTask: function (card) {
        var player = this.getCurPlayer();

        // if (!player.isBaoTing()) {
        //     var tings = player.checkTing();
        //     if (tings.length > 0) {
        //         this._hangupTask.addTingTask(player.getIndex(), tings);
        //         player.setTingCards(tings);
        //     }
        // }

        this._checkPlayCardHangupTask(card);
    },
    //检查出牌后其它玩家的挂起任务
    _checkPlayCardHangupTask: function (card) {
        var curPlay = this.getCurPlay();//当前玩家的座次
        var curPlayer = this.getCurPlayer();//当前玩家对象

        var huTesks = [];
        this.enumPlayers(function (eIndex, ePlayer) {//枚举所有玩家
            var tings = ePlayer.checkTing();
            ePlayer.setTingCards(tings);
            if (eIndex != curPlay) { //如果不是当前玩家
                if (!ePlayer.isPassHu()) {//玩家没有跳过胡牌
                    var huPattern = ePlayer.checkHuWithCard(card);//检查是否能胡这张牌，能则获取胡的牌型
                    var tingLength = ePlayer.getTingCards().length;
                    var cards = ePlayer.getHandCards();
                    // 判断 清一色/豪华清一色/全求人清一色
                    var colors = ePlayer.getColorsWithCards(cards).length;
                    if (huPattern && huPattern != MJ.Pattern.NONE) {//如果可以胡牌的话
                        if (huPattern == MJ.Pattern.NORMAL && tingLength >= 2 && colors > 1) {//(不是清一色)平湖听两张牌以上 就不能接炮 只能自摸
                            if (!ePlayer.isBaoTing()) {//玩家没有报听,就检查是否有碰牌或者杠牌
                                if (ePlayer.checkPengWithCard(card)) {
                                    this._hangupTask.addPengTask(eIndex, card, curPlay);
                                }
                                if (ePlayer.checkGangWithCard(card)) {
                                    this._hangupTask.addGangTask(eIndex, [{
                                        card: card,
                                        from: curPlay,
                                        gang: MJ.Gang.DIAN
                                    }]);
                                }
                            }
                            return;
                        }
                        var rules = [];
                        var dealerFirstCard = this.getPlayerByIndex(this.getDealerIndex()).getPlayHand() == 1 ? true : false;
                        if (dealerFirstCard && curPlay == this.getDealerIndex()) {//当前玩家是庄家，且是第一个手牌
                            rules.push(Const.ScoreRule.DIHU);
                        } else if (ePlayer.isBaoTing()) {
                            rules.push(Const.ScoreRule.BT);
                        }

                        var huTesk = new Object();
                        huTesk.huIndex = eIndex;
                        huTesk.huCard = card;
                        huTesk.from = curPlay;
                        huTesk.pattern = huPattern;
                        huTesk.rules = rules;
                        huTesks.push(huTesk);
                    }
                }

                if (!ePlayer.isBaoTing()) {//玩家没有报听,就检查是否有碰牌或者杠牌
                    if (ePlayer.checkPengWithCard(card)) {
                        this._hangupTask.addPengTask(eIndex, card, curPlay);
                    }
                    if (ePlayer.checkGangWithCard(card)) {
                        this._hangupTask.addGangTask(eIndex, [{
                            card: card,
                            from: curPlay,
                            gang: MJ.Gang.DIAN
                        }]);
                    }
                }
            }
        }.bind(this));

        huTesks.forEach(function (huTesk) {
            this._hangupTask.addHuTask(huTesk.huIndex, huTesk.huCard, huTesk.from, huTesk.pattern, huTesk.rules);
            var huPlayer = this.getPlayerByIndex(huTesk.huIndex);
            if (huPlayer && huPlayer.isBaoTing()) {
                this._hangupTask.submitTask(huTesk.huIndex, MJ.Task.HU);
            }
        }.bind(this));
    },

    /**
     * 检查当前玩家的挂起任务
     */
    checkCurPlayHangupTask: function () {
        var player = this.getCurPlayer();
        var gangArray = player.checkGang();

        if (gangArray.length > 0) {
            this._hangupTask.addGangTask(player.getIndex(), [{
                card: gangArray[0].card,
                from: player.getIndex(),
                gang: gangArray[0].gang,
                overdue: gangArray[0].overdue
            }]);
        }
        this.onAfterNewCard();
    },

    //检查杠牌后挂起事件
    checkGangHangupTask: function (playerIndex, gangInfo) {
        var card = gangInfo.card;//杠的牌

        this.enumPlayers(function (eIndex, ePlayer) {//枚举每个玩家
            if (eIndex != playerIndex) {//不是当前玩家
                var huPattern = ePlayer.checkHuWithCard(card);
                if (huPattern != MJ.Pattern.NONE) {
                    var rules = [];
                    rules.push(Const.ScoreRule.QG);//抢杠

                    if (ePlayer.isBaoTing()) {
                        rules.push(Const.ScoreRule.BT);
                    }
                    this._hangupTask.addHuTask(eIndex, card, playerIndex, huPattern, rules);
                    if (ePlayer.isBaoTing()) {
                        this._hangupTask.submitTask(eIndex, MJ.Task.HU);
                    }
                }
            }
        }.bind(this));
    },
    //检查是否可抢杠
    checkGangTaskQG: function (task, gangInfo) {
        var fromIndex = gangInfo.from;
        var card = gangInfo.card;

        var isQG = false;
        this.enumPlayers(function (eIndex, ePlayer) {
            var huPattern = ePlayer.checkHuWithCard(card);
            if (huPattern == MJ.Pattern.NORMAL) {
                isQG = gangInfo.gang == MJ.Gang.DIAN ? true : (gangInfo.gang == MJ.Gang.BA ? true : false);
            } else if (huPattern == Const.Pattern.KADAN) {
                isQG = gangInfo.gang == MJ.Gang.BA ? true : (gangInfo.gang == MJ.Gang.DIAN ? true : false);
            }
        });
        return isQG;
    },
    //出牌后处理
    onAfterPlayCard: function (player, card, playInfo) {
        this._super(player, card, playInfo);
    },

    //检查胡牌结算
    checkHuSettlement: function () {
        return true;
    },

    //胡牌处理
    onSettlementHuTask: function (task) {
        var option = this.getOption("RULE");
        if (option == 3 || option == 4) {
            this.dealMoBao();
        }
        var playerIndex = task.playerIndex;
        var pattern = task.pattern;
        var card = task.card;
        var from = task.from;
        var rules = task.rules;
        var huPlayer = this.getPlayerByIndex(playerIndex);
        var colors = huPlayer.getColorsWithCards(huPlayer.getHandCards());// 判断 清一色
        var isQYS = colors.length == 1 ? (pattern == Const.Pattern.ZYS ? false : true) : false;

        var isZM = (playerIndex == from); // 是否是自摸

        var targetsIndex = [];
        var targets = [];
        if (isZM) {
            huPlayer.setRoundScoreRule(Const.ScoreRule.ZM);
            this.enumPlayers(function (eIndex, ePlayer) {
                if (eIndex != playerIndex && !ePlayer.isRoundHu()) {
                    targetsIndex.push(eIndex);
                    targets.push(ePlayer);
                }
            });
        } else {
            var dpPlayer = this.getPlayerByIndex(from);
            dpPlayer.setRoundScoreRule(Const.ScoreRule.DH);
            targetsIndex.push(from);
            targets.push(dpPlayer);
        }

        var patternScore = Const.PatternScore[pattern]; //基础牌型分

        for (var i = 0; i < rules.length; ++i) {
            if (rules[i] == Const.ScoreRule.DIHU || rules[i] == Const.ScoreRule.TH) {
                huPlayer.setRoundScoreRule(rules[i]);
                huPlayer.addRoundItemScores(rules[i], Const.ItemScore[rules[i]]);

                var huResult = isZM ? MJ.Result.ZM : MJ.Result.DH;
                huPlayer.setRoundResult(huResult, targetsIndex, card);

                this.broadcastReplay("onPlayerHu", {
                    playerIndex: playerIndex,
                    card: card,
                    from: from,
                });
                return;
            }
        }

        for (var i = 0; i < rules.length; ++i) {
            var rule = rules[i];
            var itemScore = Const.ItemScore[rule];      //特殊规则分
            switch (rule) {
                case Const.ScoreRule.QG:
                    if (!isZM) {
                        var targetPlayer = targets[0];
                        if (targetPlayer.getIndex() == this.getCurPlay() && this.getCurGang() > 0) { // 抢杠的 被抢玩家 一定是当前玩家
                            huPlayer.setRoundScoreRule(rule);
                            if (isQYS) { // 判断是否为清一色
                                var tempRule = Const.ScoreRule.QingYiSe;
                                if (huPlayer._handCards.getCardNum() == 2) {
                                    tempRule = Const.ScoreRule.QQRQYS;
                                } else if (pattern == Const.Pattern.HHQD) {
                                    tempRule = Const.ScoreRule.HHQDQYS;
                                }
                                var qysScore = Const.ItemScore[tempRule];
                                huPlayer.setRoundScoreRule(tempRule);
                                huPlayer.addRoundItemScores(tempRule, qysScore * itemScore);
                                targetPlayer.addRoundItemScores(0, -(qysScore * itemScore));
                            }
                            targetPlayer.addRoundItemScores(0, -(itemScore * patternScore));
                            huPlayer.addRoundItemScores(rule, itemScore * patternScore - patternScore);
                            targetPlayer.unsetRoundItemScore(Const.ScoreRule.DH);
                            targetPlayer.cancelLastGangForQG(card);
                        }
                    }
                    break;
                case Const.ScoreRule.GSH:
                    if (isZM) {
                        var qysScore = 0;
                        if (isQYS) {
                            var tempRule = Const.ScoreRule.QingYiSe;
                            if (huPlayer._handCards.getCardNum() == 2) {
                                tempRule = Const.ScoreRule.QQRQYS;
                            } else if (pattern == Const.Pattern.HHQD) {
                                tempRule = Const.ScoreRule.HHQDQYS;
                            }
                            qysScore = Const.ItemScore[tempRule];
                            huPlayer.setRoundScoreRule(tempRule);
                            huPlayer.addRoundItemScores(tempRule, (qysScore * 2));
                        }
                        huPlayer.setRoundScoreRule(rule);
                        this.enumPlayers(function (eIndex, ePlayer) {
                            if (ePlayer != huPlayer) {
                                ePlayer.addRoundItemScores(0, -(patternScore * itemScore));//扣除杠开的分
                                ePlayer.addRoundItemScores(0, -qysScore);//扣除清一色的分数
                            }
                        });
                        huPlayer.addRoundItemScores(rule, patternScore * itemScore - patternScore);
                        huPlayer.unsetRoundItemScore(Const.ScoreRule.ZM);
                    }
                    break;
                default:
                    huPlayer.setRoundScoreRule(rule);
                    huPlayer.addRoundItemScores(rule, itemScore);
                    break;
            }
        }

        var huResult = isZM ? MJ.Result.ZM : MJ.Result.DH;
        huPlayer.setRoundResult(huResult, targetsIndex, card);
        huPlayer.setRoundPattern(pattern, patternScore);
        targets.forEach(function (target) {
            target.setRoundResult(-huResult);
        });

        this.broadcastReplay("onPlayerHu", {
            playerIndex: playerIndex,
            card: card,
            from: from,
        });
    },

    //结算处理
    onSettlement: function () {
        if (this.isRoundHZ()) {//流局
            this.enumPlayers(function (eIndex, ePlayer) {
                ePlayer._stat.LaZhuangScore = 0;
                ePlayer._selectLaZhuang = 0;
            }.bind(this));
            return;
        }

        this.enumPlayers(function (eIndex, ePlayer) {
            ePlayer.settlementRules();
        });

        this.enumPlayers(function (eIndex, ePlayer) {
            ePlayer.settlementGangScore();//计算杠分
            ePlayer.settlementPatternScore();//计算牌型分
        }.bind(this));

    },

    onCurRoundFinished: function () {
        this._super();

        // 计算新的庄家
        if (this.isRoundHZ()) {//如果流局,庄家的下家就是新庄家
            this._dealerIndex = this.getNextIndex(this._dealerIndex);
        } else {
            if (this.getFirstHuPlayerIndex() == this._dealerIndex) {
                this._dealerLZ++;
            } else {
                this._dealerIndex = this.getFirstHuPlayerIndex();
                this._dealerLZ = 1;
            }
        }
        this.broadcastReplay("onDealerChanged", {
            dealer: this._dealerIndex,
            dealerLZ: this._dealerLZ,
            curRounds: this._curRounds
        });
    },

    onPlayerEnter: function (player) {
        var gameRule = this.getOption("RULE");
        if (gameRule == 1 || gameRule == 3) {
            if (player._uid == this._creator) {
                this._dealerIndex = player._index;
            }
        }
        if (this.isAgency()) {
            var playerInfo = this.getPlayerByUid(player.uid()).getInfo();
            playerInfo["playerIndex"] = player.getIndex();
            this.sendToAgency("onPlayerEnterOfAgency", {"player": playerInfo, "roomIndex": this.getOption("index")});
        }
    },

    onPlayerQuitRoom: function (player) {
        if (this.isAgency()) {
            var playerInfo = this.getPlayerByUid(player.uid()).getInfo();
            playerInfo["playerIndex"] = player.getIndex();
            this.sendToAgency("onPlayerQuitRoomOfAgency", {"player": playerInfo, "roomIndex": this.getOption("index")});
        }
    },

    onDestroy: function () {
        if (this.isAgency()) {
            this.sendToAgency("onDestroyRoomOfAgency", {"rid": this.rid(), "roomIndex": this.getOption("index")});
        }
    },

    /******************************************************************
     * 消息处理
     ******************************************************************/

    handleCancelBaoTing: function (player, msg, callback) {//取消听牌
        player._isBaoTing = false;
        callback();
        this.broadcastReplay("onCancelBaoTing", {
            playerIndex: player.getIndex(),
            isBaoTing: player.isBaoTing()
        });
    },

    /******************************************************************
     * 功能接口
     ******************************************************************/

    /**
     * 结算玩家是否听牌
     * @param player
     * @private
     */
    _settlementPlayerTing: function (player) {
        //已听牌玩家不用再检测
        if (player.isRoundTing()) {
            return;
        }

        // 对未胡牌的玩家检查是否听牌
        var tings = player.checkTing();
        var pattern = Const.Pattern.NONE;
        var patternScore = 0;
        for (var i = 0; i < tings.length; ++i) {
            var ting = tings[i];
            var score = Const.PatternScore[ting.pattern];
            if (score > patternScore) {
                pattern = ting.pattern;
                patternScore = score;
            }
        }

        player.setRoundPattern(pattern, 0);
    },

    /******************************************************************
     * 私有功能
     ******************************************************************/
    dealMoBao: function () {
        if (this._publicCards.getRemainNum() < 1) {
            this._baoCard = -1;
            this._baoIndex = -1;
            return;
        }
        var nextCard = this._publicCards.lookCard();
        this._baoCard = nextCard;
        var point = MJ.getPoint(nextCard);
        var playerNum = this.getMaxPlayer();
        if (nextCard <= 7) {
            if (playerNum == 3) {
                var index = this.getDealerIndex();
                var temp = point % 4;
                if (temp == 0) {
                    temp = 1;
                }
                while (temp != 1) {
                    index = this.getNextIndex(index);
                    temp--;
                }
                this._baoIndex = index;
                return;
            }
        }
        this._baoIndex = ((point % playerNum) + this.getIndexDistance(1, this.getDealerIndex())) % playerNum;
        if (this._baoIndex == 0) {
            this._baoIndex = playerNum;
        }
    },

    getSettlementInfo: function () {//获取结算信息
        var info = this._super();
        info.isHZ = this.isRoundHZ(); // 是否黄庄家
        info.dealerIndex = this.getDealerIndex();
        info.dealerLZ = this.getDealerLZ();
        info.baoCard = this._baoCard;
        info.baoIndex = this._baoIndex;
        return info;
    },

    /******************************************************************
     * 消息处理
     ******************************************************************/

    handleGift: function (player, msg, callback) {
        if (isNaN(msg.targetIndex)) {
            callback({code: Code.ARGS_INVALID});
            return;
        }

        var gameConfig = this.getGameConfig();
        var giftType = msg.type;
        var giftConfig = gameConfig.Gift[giftType];
        if (!giftConfig) {
            callback({code: Code.ARGS_VALUE_WRONG});
            return;
        }

        var targetIndex = parseInt(msg.targetIndex);
        var targetPlayer = this.getPlayerByIndex(targetIndex);
        if (!targetPlayer) {
            callback({code: SubCode.INDEX_INVALID});
            return;
        }

        if (!player.checkResource(giftConfig.costs)) {
            callback({code: Code.LACK_OF_COIN});
            return;
        }

        this.broadcast("onPlayerGift", {
            playerIndex: player.getIndex(),
            targetIndex: targetIndex,
            type: giftType
        });
        callback();

        player.costResourceSync(giftConfig.costs);
        // targetPlayer.addResourceSync(giftConfig.harvest);
    },

    // handleCurPlayerTingInfo: function (player, msg, callback) {
    //
    // },

    handleEnjoy: function (player, msg, callback) {
        callback();

        var gameConfig = this.getGameConfig();
        player.costResourceSync(gameConfig.Enjoy.costs);
    },
    /******************************************************************
     * 听牌 ---- 分数
     ******************************************************************/

    // getTingInfo: function (curPlayer) {
    //     var json = {};
    //     // var curPlayer = this.getCurPlayer();
    //     if (curPlayer.isBaoTing()) {
    //         curPlayer.send("onPlayerTingInfo", {});
    //         return;
    //     }
    //     var handCards = curPlayer.getHandCards();
    //     var isPeng = this.isPeng(curPlayer, handCards);
    //     var dealer = this.getPlayerByIndex(this.getDealerIndex());
    //     var tingInfo;
    //     if (isPeng) {
    //         tingInfo = this.getCurPlayerTingInfo(curPlayer, handCards);
    //     } else {
    //         if (curPlayer == dealer) {
    //             if (!dealer.isFirstHand()) {
    //                 var nextCard = this._publicCards.lookCard();
    //                 ExObject.addNumber(handCards, nextCard, 1);
    //             }
    //         } else {
    //             var nextCard = this._publicCards.lookCard();
    //             ExObject.addNumber(handCards, nextCard, 1);
    //         }
    //         tingInfo = this.getCurPlayerTingInfo(curPlayer, handCards);
    //         var num = handCards[nextCard];
    //         if (num) {
    //             if (num <= 1) {
    //                 delete handCards[nextCard];
    //             } else {
    //                 handCards[nextCard] = num - 1;
    //             }
    //         }
    //     }
    //     if (tingInfo) {
    //         json = this.arrayToJSON(tingInfo);
    //     }
    //     return json;
    // },

    // onCurPlayChanged: function () {
    //     var json;
    //     var curPlayer = this.getCurPlayer();
    //     if (curPlayer.isBaoTing()) {
    //         curPlayer.send("onPlayerTingInfo", {});
    //         return;
    //     }
    //     var handCards = curPlayer.getHandCards();
    //     var isPeng = this.isPeng(curPlayer, handCards);
    //     var dealer = this.getPlayerByIndex(this.getDealerIndex());
    //     var tingInfo;
    //     if (isPeng) {
    //         tingInfo = this.getCurPlayerTingInfo(curPlayer, handCards);
    //     } else {
    //         if (curPlayer == dealer) {
    //             if (!dealer.isFirstHand()) {
    //                 var nextCard = this._publicCards.lookCard();
    //                 ExObject.addNumber(handCards, nextCard, 1);
    //             }
    //         } else {
    //             var nextCard = this._publicCards.lookCard();
    //             ExObject.addNumber(handCards, nextCard, 1);
    //         }
    //         tingInfo = this.getCurPlayerTingInfo(curPlayer, handCards);
    //         var num = handCards[nextCard];
    //         if (num) {
    //             if (num <= 1) {
    //                 delete handCards[nextCard];
    //             } else {
    //                 handCards[nextCard] = num - 1;
    //             }
    //         }
    //     }
    //     if (tingInfo) {
    //         json = this.arrayToJSON(tingInfo);
    //     }
    //     curPlayer.send("onPlayerTingInfo", json);
    // },

    arrayToJSON: function (array) {
        var json = {};
        array.forEach(function (info) {
            var ar = new Array();
            if (json[info.play]) {
                ar = json[info.play];
                delete json[info.play];
            }
            ar.push({"card": info.ting, "left": info.left, "score": info.score});
            json[info.play] = ar;
            // json[info.play] = {"card": info.ting, "left": info.left, "score": info.score};
        });
        return json;
    },

    getLeftCard: function (curPlayer, playWithTing) {
        playWithTing.forEach(function (info) {
            var tingCard = info.ting;
            var left = 0;
            var nextCard = this._publicCards.lookCard();
            this.enumPlayers(function (eIndex, ePlayer) {
                if (ePlayer != curPlayer) {
                    var handCard = ePlayer.getHandCards();
                    var num = handCard[tingCard];
                    if (num) {
                        left += num;
                    }
                }
            });
            var remainCard = this._publicCards.getRemainCards();
            for (var i = 0; i < remainCard.length; ++i) {
                if (remainCard[i] == tingCard) {
                    left++;
                }
            }
            info.left = left;
            if (nextCard == tingCard) {
                info.left--;
            }
        }.bind(this));
        return playWithTing;
    },

    getCurPlayerTingInfo: function (curPlayer, handCards) {
        var tempCards = clone(handCards);
        var playWithTing = this.getPlayWithTing(curPlayer, tempCards);
        return this.getLeftCard(curPlayer, playWithTing);
    },

    getPlayWithTing: function (curPlayer, tempCards) {
        var playWithTing = [];
        ExObject.each(tempCards, function (card, num) {
            if (num) {
                if (num <= 1) {
                    delete tempCards[card];
                } else {
                    tempCards[card] = num - 1;
                }
            }
            var tingCards = this.checkTingCard(curPlayer, tempCards);
            if (tingCards.length == 1) {
                tingCards[0].pattern = Const.Pattern.KADAN;
            }

            var colors = curPlayer.getColorsWithCards(tempCards);

            tingCards.forEach(function (tingInfo) {
                var info = {};
                info.play = card;
                info.ting = tingInfo.card;
                info.score = this.getPatternScore(tingInfo.pattern, colors);

                playWithTing.push(info);
            }.bind(this));
            ExObject.addNumber(tempCards, card, 1);
        }.bind(this));
        return playWithTing;
    },

    checkTingCard: function (player, cards) {
        var tings = [];
        var subConfig = this.getSubConfig();

        subConfig.colors.forEach(function (color) {
            var cardNum = MJ.ColorCardNum[color];
            for (var p = 1, pm = cardNum.point; p <= pm; ++p) {
                var card = MJ.getValue(color, p);
                if (cards[card] === 4) {
                    continue;
                }

                var tmpCards = clone(cards);
                ExObject.addNumber(tmpCards, card, 1);

                var pattern = player.checkHuLogic(tmpCards, card);
                if (pattern != MJ.Pattern.NONE) {
                    tings.push({card: card, pattern: pattern});
                }
            }
        });
        return tings;
    },

    getPatternScore: function (pattern, colors) {
        var score = 0;
        var playerNum = this.getMaxPlayer();
        var itemScore = 0;

        if (colors.length == 1) {
            var rule = Const.ScoreRule.QingYiSe;
            if (pattern == Const.Pattern.SINGLE) {
                rule = Const.ScoreRule.QQRQYS;
            } else if (pattern == Const.Pattern.HHQD) {
                rule = Const.ScoreRule.HHQDQYS;
            }
            itemScore = Const.ItemScore[rule];
        }

        switch (pattern) {
            case Const.Pattern.NORMAL:
                var tmpScore = 1;
                if (itemScore != 0) {
                    tmpScore += itemScore;
                }
                if (playerNum == 4)
                    score = tmpScore * 3;
                else
                    score = tmpScore * 2;
                break;
            case Const.Pattern.KADAN:
                var tmpScore = 2;
                if (itemScore != 0) {
                    tmpScore += itemScore;
                }
                if (playerNum == 4)
                    score = tmpScore * 3;
                else
                    score = tmpScore * 2;
                break;
            case Const.Pattern.PAIR:
                var tmpScore = 3;
                if (itemScore != 0) {
                    tmpScore += itemScore;
                }
                if (playerNum == 4)
                    score = tmpScore * 3;
                else
                    score = tmpScore * 2;
                break;
            case Const.Pattern.PAIR7:
                var tmpScore = 4;
                if (itemScore != 0) {
                    tmpScore += itemScore;
                }
                if (playerNum == 4)
                    score = tmpScore * 3;
                else
                    score = tmpScore * 2;
                break;
            case Const.Pattern.SINGLE:
                var tmpScore = 5;
                if (itemScore != 0) {
                    tmpScore += itemScore;
                }
                if (playerNum == 4)
                    score = tmpScore * 3;
                else
                    score = tmpScore * 2;
                break;
            case Const.Pattern.HHQD:
                var tmpScore = 8;
                if (itemScore != 0) {
                    tmpScore += itemScore;
                }
                if (playerNum == 4)
                    score = tmpScore * 3;
                else
                    score = tmpScore * 2;
                break;
            case Const.Pattern.ZYS:
                var tmpScore = 5;
                if (itemScore != 0) {
                    tmpScore += itemScore;
                }
                if (playerNum == 4)
                    score = tmpScore * 3;
                else
                    score = tmpScore * 2;
                break;
        }
        return score;
    },

    isPeng: function (player, cards) {
        var numAll = 0;
        ExObject.each(cards, function (c, n) {
            numAll += n;
        });
        if ((numAll - 2) % 3 == 0) {
            return true;
        } else {
            return false;
        }
    },
});